package com.marvels.financial.loan.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.util.StringUtil;
import com.marvels.common.constants.ExtensionFunctionEnum;
import com.marvels.common.constants.MarvelsConstant;
import com.marvels.common.constants.RedisKeyConstant;
import com.marvels.common.dto.UserDTO;
import com.marvels.common.dto.pay.MarvelsPayResultDTO;
import com.marvels.common.dto.pay.McfePaymentUserBindCard;
import com.marvels.common.dto.pay.McfeRepaymentTradeDetails;
import com.marvels.common.exception.MarvelsBusinessException;
import com.marvels.common.utils.*;
import com.marvels.financial.collection.dao.OverdueCollectTaskDao;
import com.marvels.financial.loan.dao.*;
import com.marvels.financial.loan.dto.*;
import com.marvels.financial.loan.service.HandleWithholdApi;
import com.marvels.financial.loan.service.TransferPaymentApi;
import com.marvels.financial.pay.dao.McfePaymentUserBindCardMapper;
import com.marvels.financial.pay.dto.WithholdConditionDTO;
import com.marvels.financial.pay.service.PayService;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @author 11271
 * @date 2024/3/13 11:48
 * @Description:
 */
@Service
public class TransferPaymentImpl implements TransferPaymentApi {
    @Autowired
    private McfeCustomerRepaymentPlanDao mcfeCustomerRepaymentPlanDao;

    @Value("${config.properties.path}")
    private  String configPropertiesPath;


    @Autowired
    private McfePaymentWithholdDetailDao withholdDetailDao;

    @Autowired
    private McfeCustomerLoanContractDao mcfeCustomerLoanContractDao;

    @Autowired
    private McfePaymentWithholdDetailDao detailDao;

    @Autowired
    private McfeRepaymentFlowDao flowDao;

    @Autowired
    private McfePaymentTransferDao transferDao;

    @Autowired
    private HandleWithholdApi handleWithholdApi;

    @Autowired
    private McfeRepaymentFlowDao mcfeRepaymentFlowDao;

    @Autowired
    private PayService payService;

    @Autowired
    private McfeLendingProcessDao mcfeLendingProcessDao;

    @Autowired
    private McfePaymentUserBindCardMapper mcamPaymentUserBindCardMapper;

    @Autowired
    private OverdueCollectTaskDao overdueCollectTaskDao;

    @Override
    public PaymentResponse withholdPayment(HandleWithholePaymentDTO conditionDto){
        PaymentResponse paymentResponse = new PaymentResponse();
        if (StringUtils.isEmpty(conditionDto.getFundSource())) {
            paymentResponse.setCode("-1");
            paymentResponse.setMsg("资金源不能为空");
            return paymentResponse;
        }

        if (StringUtils.isEmpty(conditionDto.getMerchantTreatyNo())) {
            paymentResponse.setCode("-1");
            paymentResponse.setMsg("用户id不能为空");
            return paymentResponse;
        }

        if (StringUtils.isEmpty(conditionDto.getReqNo())) {
            paymentResponse.setCode("-1");
            paymentResponse.setMsg("请求编号不能为空");
            return paymentResponse;
        }

        if (StringUtils.isEmpty(conditionDto.getCustName())) {
            paymentResponse.setCode("-1");
            paymentResponse.setMsg("姓名不能为空");
            return paymentResponse;
        }

        if (StringUtils.isEmpty(conditionDto.getBankName())) {
            paymentResponse.setCode("-1");
            paymentResponse.setMsg("银行名称不能为空");
            return paymentResponse;
        }

        if (StringUtils.isEmpty(conditionDto.getCustBankAccountNo())) {
            paymentResponse.setCode("-1");
            paymentResponse.setMsg("银行卡号不能为空");
            return paymentResponse;
        }

        if (conditionDto.getAmount() == null) {
            paymentResponse.setCode("-1");
            paymentResponse.setMsg("交易金额不能为空");
            return paymentResponse;
        }

        if (conditionDto.getAmount().compareTo(new BigDecimal("0")) < 1) {
            paymentResponse.setCode("-1");
            paymentResponse.setMsg("交易金额不能为0");
            return paymentResponse;
        }

        if (StringUtils.isEmpty(conditionDto.getRemark())) {
            paymentResponse.setCode("-1");
            paymentResponse.setMsg("备注不能为空");
            return paymentResponse;
        }
        if (StringUtils.isEmpty(conditionDto.getCustBindPhoneNo())) {
            paymentResponse.setCode("-1");
            paymentResponse.setMsg("手机号码不能为空");
            return paymentResponse;
        }

        if (StringUtils.isEmpty(conditionDto.getCustBankAcctType())) {
            paymentResponse.setCode("-1");
            paymentResponse.setMsg("客户银行卡类型不能为空");
            return paymentResponse;
        }

        if (StringUtils.isEmpty(conditionDto.getCustId())) {
            paymentResponse.setCode("-1");
            paymentResponse.setMsg("身份证号码不能为空");
            return paymentResponse;
        }
        BigDecimal amount = conditionDto.getAmount().setScale(2, BigDecimal.ROUND_HALF_UP);
        MarvelsLogUtil.getInstance().info(">>>>>>>>>>>>>>loanId:" + conditionDto.getLoanId() + ",身份证:" + conditionDto.getCustId() + ",银行卡号:"
                + conditionDto.getCustBankAccountNo() + ",代扣请求参数:" + conditionDto);
        MarvelsPayResultDTO marvelsResultDTO=null;
        String paymentChannel="";
        if(StringUtils.isNotEmpty(conditionDto.getPaymentChannel())){
            paymentChannel=conditionDto.getPaymentChannel();
        }else{
            paymentChannel= ServerProperties.getValue(configPropertiesPath, "common.properties", "payment_channel");
        }
        WithholdConditionDTO dto=new WithholdConditionDTO();
        dto.setRequestNo(conditionDto.getReqNo());
        dto.setIdno(conditionDto.getCustId());
        dto.setBindCard(conditionDto.getCustBankAccountNo());
        dto.setAmount(amount.toString());
        dto.setTitle("还款代扣");
        dto.setChannel(paymentChannel);
        dto.setType(conditionDto.getType());
        dto.setBankName(conditionDto.getBankName());
        dto.setCustName(conditionDto.getCustName());
        dto.setMobile(conditionDto.getCustBindPhoneNo());
        dto.setT2SmsCode(conditionDto.getT2SmsCode());
        dto.setLoanId(conditionDto.getLoanId());
        try {
            marvelsResultDTO = payService.withhold(dto);
        } catch (Exception e) {
            MarvelsLogUtil.getInstance().error(">>>>>>>>>>>>>>loanId:" + conditionDto.getLoanId() + ",身份证:" + conditionDto.getCustId() + ",银行卡号:"
                    + conditionDto.getCustBankAccountNo() + ",第三方代扣异常" ,e);
        }
        MarvelsLogUtil.getInstance().info(">>>>>>>>>>>>>>loanId:" + conditionDto.getLoanId() + ",身份证:" + conditionDto.getCustId() + ",银行卡号:"
                + conditionDto.getCustBankAccountNo() + ",走第三方代扣返回参数:" + marvelsResultDTO);

        String status = "";
        String rtnOrderNo = "";// 第三方返回订单号
        String rtnResponseCode = "";// 扣款返回码
        String rtnResponseMsg = "";// 扣款返回信息
        BigDecimal successAmount = BigDecimal.valueOf(0);
        PaymentResponse paymentResponseReturn = new PaymentResponse();
        paymentResponseReturn.setChannel(paymentChannel);
        if (null == marvelsResultDTO) {
            status = MarvelsConstant.FAILED;
            rtnResponseMsg = "返回信息为空";
        } else {
            rtnResponseMsg = marvelsResultDTO.getMessage();
            rtnResponseCode = marvelsResultDTO.getCode();
            if ("0".equals(rtnResponseCode)) {
                McfeRepaymentTradeDetails mcamRepaymentTradeDetails = (McfeRepaymentTradeDetails)marvelsResultDTO.getData();
                //代扣状态
                if(mcamRepaymentTradeDetails != null){
                    String returnStatus = mcamRepaymentTradeDetails.getResult();
                    rtnOrderNo = mcamRepaymentTradeDetails.getPayOrderNumber();
                    paymentResponseReturn.setOrderNumber(rtnOrderNo);
                    if("0".equals(returnStatus)){
                        // 成功
                        status = MarvelsConstant.SUCCESS;
                        successAmount = conditionDto.getAmount();
                        paymentResponseReturn.setSuccessAmount(successAmount);
                    }else if("-1".equals(returnStatus)){
                        //失败
                        status = MarvelsConstant.FAILED;
                    }else{
                        //其余，做代扣中处理
                        status = MarvelsConstant.PROCESSING;
                    }
                }else{
                    //按理不会进入这个逻辑
                    status = MarvelsConstant.FAILED;
                    rtnResponseMsg = "返回代扣信息为空";
                }


            }else{
                //做代扣中处理
                status = MarvelsConstant.FAILED;
            }
        }

        paymentResponseReturn.setCode(status);
        paymentResponseReturn.setMsg(rtnResponseMsg);
        paymentResponseReturn.setSuccessAmount(successAmount);
        paymentResponseReturn.setChannel(paymentChannel);

        return paymentResponseReturn;
    }

    @Override
    public PaymentResponse withholdPaymentQuery(WithholeQueryConditionDTO dto) {
        String paymenChannel  = ServerProperties.getValue(configPropertiesPath, "common.properties", "payment_channel");
        MarvelsPayResultDTO marvelsResultDTO = payService.queryWithholdResult(dto.getOrderNumber(),paymenChannel,dto.getPayType());
        String status = "";
        String rtnOrderNo = "";// 第三方返回订单号
        String rtnResponseCode = "";// 扣款返回码
        String rtnResponseMsg = "";// 扣款返回信息
        BigDecimal successAmount = BigDecimal.valueOf(0);
        PaymentResponse paymentResponseReturn = new PaymentResponse();
        if (null == marvelsResultDTO) {
            status = MarvelsConstant.PROCESSING;
            rtnResponseMsg = "返回信息为空";
        } else {
            rtnResponseMsg = marvelsResultDTO.getMessage();
            rtnResponseCode = marvelsResultDTO.getCode();
            if ("0".equals(rtnResponseCode)) {
                McfeRepaymentTradeDetails mcamRepaymentTradeDetails = (McfeRepaymentTradeDetails)marvelsResultDTO.getData();
                //代扣状态
                if(mcamRepaymentTradeDetails != null){
                    paymentResponseReturn.setChannel(mcamRepaymentTradeDetails.getChannel());
                    String returnStatus = mcamRepaymentTradeDetails.getResult();
                    rtnOrderNo = mcamRepaymentTradeDetails.getPayOrderNumber();
                    if("0".equals(returnStatus)){
                        // 成功
                        status = MarvelsConstant.SUCCESS;
                        paymentResponseReturn.setOrderNumber(rtnOrderNo);
                        String amount = mcamRepaymentTradeDetails.getAmount();
                        if(StringUtils.isNotEmpty(amount)){
                            successAmount = BigDecimal.valueOf(Double.valueOf(amount));
                        }
                        paymentResponseReturn.setSuccessAmount(successAmount);
                    }else if("-1".equals(returnStatus) || "-3".equals(returnStatus)){
                        //失败
                        status = MarvelsConstant.FAILED;
                        rtnResponseMsg = "代扣失败";
                    }else{
                        //其余，做代扣中处理
                        status = MarvelsConstant.PROCESSING;
                        rtnResponseMsg = "代扣中";
                    }
                }


            }else{
                //做代扣中处理
                status = MarvelsConstant.PROCESSING;
                rtnResponseMsg = "代扣中";
            }
        }

        paymentResponseReturn.setCode(status);
        paymentResponseReturn.setMsg(rtnResponseMsg);
        paymentResponseReturn.setSuccessAmount(successAmount);
        return paymentResponseReturn;
    }



    /**
     *
     * @Title: withholdCommonDeal
     * @Description:扣款公用接口(非提前结清)
     * @param paymentWithholdDTO
     * @return
     * @throws MarvelsBusinessException
     * @author 李瑶
     * @date 2018年10月20日 下午2:03:17
     */
    @Override
    public PaymentResponse withholdCommonDeal(McfePaymentWithholdDTO paymentWithholdDTO) throws MarvelsBusinessException{
        MarvelsLogUtil.getInstance().info(">>>>>>>>扣款请求参数:" + JSONObject.fromObject(paymentWithholdDTO));
        String loanId=paymentWithholdDTO.getLoanId();
        if(StringUtils.isEmpty(loanId)){
            throw new MarvelsBusinessException("loanId不能为空");
        }
        if(paymentWithholdDTO.getAmount()==null || paymentWithholdDTO.getAmount().compareTo(BigDecimal.ZERO)<1){
            throw new MarvelsBusinessException("金额必须大于0");
        }
        if(StringUtils.isEmpty(paymentWithholdDTO.getBankCardNo())){
            throw new MarvelsBusinessException("银行卡号不能为空");
        }
        if(StringUtils.isEmpty(paymentWithholdDTO.getBankName())){
            throw new MarvelsBusinessException("银行名称不能为空");
        }
        if(StringUtils.isEmpty(paymentWithholdDTO.getCustCardNo())){
            throw new MarvelsBusinessException("身份证号不能为空");
        }
        if(StringUtils.isEmpty(paymentWithholdDTO.getTransctionSeq())){
            throw new MarvelsBusinessException("请求编号不能为空");
        }
        String withholdCategory=paymentWithholdDTO.getWithholdCategory();
        if(StringUtils.isEmpty(withholdCategory) || (StringUtils.isNotEmpty(withholdCategory) && withholdCategory.equals("1"))){
            if(StringUtils.isEmpty(paymentWithholdDTO.getRepayStyle())){
                throw new MarvelsBusinessException("还款方式不能为空");
            }
            if(StringUtils.isEmpty(paymentWithholdDTO.getFlowPayType()) ){
                throw new MarvelsBusinessException("还款类型不能为空");
            }
        }
        if(StringUtils.isNotEmpty(withholdCategory) && withholdCategory.equals("2")){
            if(paymentWithholdDTO.getExtensionDay()==null){
                throw new MarvelsBusinessException("展期天数不能为空");
            }
        }
        // 加锁 避免重复插入数据
        String key = RedisKeyConstant.HAND_PAYMENT_WITHHOLD + loanId;
        boolean isNotLock = false;
        try {
            isNotLock = CacheUtils.isNotLock(key, loanId);
            if (isNotLock) {
                // 先将这个key设置过期时间
                CacheUtils.setExpire(key, 60);
                McfeCustomerLoanContractDTO contractDTO = mcfeCustomerLoanContractDao.selectContractByLoanId(loanId);
                if (null == contractDTO) {
                    throw new MarvelsBusinessException("合同信息不存在");
                }
                if (2==contractDTO.getStatus() || 3==contractDTO.getStatus()
                        || 10==contractDTO.getStatus()) {
                    throw new MarvelsBusinessException("进件不处于还款状态");
                }
                String type=paymentWithholdDTO.getType();
				/*
				 * //不是直接代扣则同步绑卡信息
				 * if(!"1".equals(type)){
					//同步合同信息
					synchronizedBankCard(contractDTO, null);
				}*/
                // 判断还款计划对应的进件是否有处在交易中的代扣
                McfePaymentWithholdDetailDTO detailDTO = detailDao.selectTradingByLoanId(loanId);
                if (detailDTO != null) {
                    MarvelsLogUtil.getInstance().info(">>>>>>>>>>loanId:" + loanId + ",有处在交易中的代扣");
                    throw new MarvelsBusinessException("存在处理中的代扣,请稍候再试");
                }
                // 判断还款计划对应的进件是否有处在正在冲账中的流水
                McfeRepaymentFlowDTO flowDTO = flowDao.selectDealingByLoanId(loanId);
                if (flowDTO != null) {
                    MarvelsLogUtil.getInstance().info(">>>>>>>>>>loanId:" + loanId + ",有处在冲账中或未冲账的流水");
                    throw new MarvelsBusinessException("存在未冲账的流水,请稍候再试");
                }
                // 拆分金额
                BigDecimal[] splitAmount = handleWithholdApi.amountSplit(paymentWithholdDTO.getAmount(), paymentWithholdDTO.getBankHeadLink());
                if (null == splitAmount || splitAmount.length < 1) {
                    splitAmount = new BigDecimal[] { paymentWithholdDTO.getAmount() };
                }
                UserDTO user = null;
                try {
                    user=CacheUtils.getCacheUser();
                } catch (Exception e) {
                    MarvelsLogUtil.getInstance().error(">>>>获取本地用户信息失败");
                }
                String userCode=user==null?"system":user.getUserCode();
                // 插入代扣总记录
                paymentWithholdDTO.setChannelCode(contractDTO.getChannelCode());
                paymentWithholdDTO.setChannelName(contractDTO.getChannelName());
                paymentWithholdDTO.setCreatedBy(userCode);
                paymentWithholdDTO.setCreatedDate(new Date());
                if(!"1".equals(type)){
                    paymentWithholdDTO.setCustName(contractDTO.getCustName());
                }
                paymentWithholdDTO.setFundCode(contractDTO.getFundCode());
                paymentWithholdDTO.setFundName(contractDTO.getFundName());
                paymentWithholdDTO.setLoanId(contractDTO.getLoanId());
                paymentWithholdDTO.setPayCount(splitAmount.length);
                paymentWithholdDTO.setPayType(StringUtils.isEmpty(paymentWithholdDTO.getRepayStyle())?4:Integer.parseInt(paymentWithholdDTO.getRepayStyle()));// 还款类型: 1-自动代扣;2-当前还款;3-提前结清;4-自定义还款;5-下期还款; 6-手动代扣 ; 9-支付宝还款 10-支付宝提前结清'
                paymentWithholdDTO.setProductCode(contractDTO.getProductCode());
                paymentWithholdDTO.setProductName(contractDTO.getProductName());
                paymentWithholdDTO.setProductType(contractDTO.getProductType());
                paymentWithholdDTO.setProductTypeName(contractDTO.getProductTypeName());
                paymentWithholdDTO.setStatus("2");// 代扣中
                paymentWithholdDTO.setUpdatedBy(userCode);
                paymentWithholdDTO.setUpdatedDate(new Date());
                paymentWithholdDTO.setWithholdCode(paymentWithholdDTO.getTransctionSeq());
                McfePaymentTransferDTO mcfePaymentTransferDTO = new McfePaymentTransferDTO();
                BeanUtil.copyProperties(paymentWithholdDTO,mcfePaymentTransferDTO);
                MarvelsLogUtil.getInstance().info(mcfePaymentTransferDTO.toString());
                int count = transferDao.insertSelective(mcfePaymentTransferDTO);
                if (count < 1) {
                    throw new MarvelsBusinessException("持久化代扣申请失败");
                }
                BigDecimal succcessAmount = new BigDecimal("0.00");
                // 将金额循环支付
                PaymentResponse totalResponse=new PaymentResponse();
                List<PaymentResponse.SingleResult> singleResults=new ArrayList<PaymentResponse.SingleResult>();
                for (int i = 0; i < splitAmount.length; i++) {
                    // 持久化代扣流水
                    String reqNo = GenerateReqNoUtils.transctionReq("TX");
                    detailDTO = new McfePaymentWithholdDetailDTO();
                    detailDTO.setAmount(splitAmount[i]);
                    detailDTO.setBankHeadLink(paymentWithholdDTO.getBankHeadLink());
                    detailDTO.setChannelCode(contractDTO.getChannelCode());
                    detailDTO.setChannelName(contractDTO.getChannelName());
                    detailDTO.setExtensionDay(paymentWithholdDTO.getExtensionDay());
                    detailDTO.setWithholdCategory(paymentWithholdDTO.getWithholdCategory());
                    detailDTO.setCreatedBy(userCode);
                    detailDTO.setCreatedDate(new Date());
                    detailDTO.setFundCode(contractDTO.getFundCode());
                    detailDTO.setFundName(contractDTO.getFundName());
                    detailDTO.setLoanId(contractDTO.getLoanId());
                    detailDTO.setPayType(StringUtils.isEmpty(paymentWithholdDTO.getRepayStyle())?"11":paymentWithholdDTO.getRepayStyle());
                    detailDTO.setProductCode(contractDTO.getProductCode());
                    detailDTO.setProductName(contractDTO.getProductName());
                    detailDTO.setProductType(contractDTO.getProductType());
                    detailDTO.setProductTypeName(contractDTO.getProductTypeName());
                    if(StringUtils.isNotEmpty(paymentWithholdDTO.getReqChannel())){
                        detailDTO.setReqChannel(paymentWithholdDTO.getReqChannel());
                    }
                    detailDTO.setStatus("1");// 交易中
                    detailDTO.setTranctionDate(new Date());
                    detailDTO.setTransctionSeq(reqNo);
                    detailDTO.setUpdatedBy(userCode);
                    detailDTO.setUpdatedDate(new Date());
                    detailDTO.setWithholdCode(paymentWithholdDTO.getTransctionSeq());

                    detailDTO.setBankName(paymentWithholdDTO.getBankName());
                    detailDTO.setBankCardNo(paymentWithholdDTO.getBankCardNo());
                    detailDTO.setCustCardNo(paymentWithholdDTO.getCustCardNo());
                    detailDTO.setCustName(paymentWithholdDTO.getCustName());
                    detailDTO.setMobile(paymentWithholdDTO.getMobile() == null ? contractDTO.getMobile() : paymentWithholdDTO.getMobile());
                    detailDTO.setBatchStatus("1");//初始化为处理中，不然查结果和主动代扣会冲突
					/*if("1".equals(type)){
						detailDTO.setBankName(paymentWithholdDTO.getBankName());
						detailDTO.setBankCardNo(paymentWithholdDTO.getBankCardNo());
						detailDTO.setCustCardNo(paymentWithholdDTO.getCustCardNo());
						detailDTO.setCustName(paymentWithholdDTO.getCustName());
						detailDTO.setMobile(paymentWithholdDTO.getMobile());
					}else{
						detailDTO.setBankName(contractDTO.getPaymentBankName());
						detailDTO.setBankCardNo(contractDTO.getPaymentAcctNo());
						detailDTO.setCustCardNo(contractDTO.getCustCardNo());
						detailDTO.setCustName(contractDTO.getCustName());
						detailDTO.setMobile(contractDTO.getMobile());
					}*/
                    int detailCount = withholdDetailDao.insertSelective(detailDTO);
                    if (detailCount < 1) {
                        continue;
                    }
                    // 发起代扣
                    HandleWithholePaymentDTO paymentDTO = new HandleWithholePaymentDTO();
                    paymentDTO.setType(type);
                    paymentDTO.setAmount(splitAmount[i]);
                    paymentDTO.setCustBankAcctType("1");
                    paymentDTO.setFundSource(contractDTO.getFundCode());
                    paymentDTO.setLoanId(contractDTO.getLoanId());
                    paymentDTO.setMerchantTreatyNo(contractDTO.getLoanId());

                    paymentDTO.setBankName(paymentWithholdDTO.getBankName());
                    paymentDTO.setCustBankAccountNo(paymentWithholdDTO.getBankCardNo());
                    paymentDTO.setCustBindPhoneNo(paymentWithholdDTO.getMobile() == null ? contractDTO.getMobile() : paymentWithholdDTO.getMobile());
                    paymentDTO.setCustId(paymentWithholdDTO.getCustCardNo());
                    paymentDTO.setCustName(paymentWithholdDTO.getCustName());
                    if("1".equals(type)){
                        paymentDTO.setT2SmsCode(paymentWithholdDTO.getT2SmsCode());
                    }
					/*else{
						paymentDTO.setBankName(contractDTO.getPaymentBankName());
						paymentDTO.setCustBankAccountNo(contractDTO.getPaymentAcctNo());
						paymentDTO.setCustBindPhoneNo(contractDTO.getMobile());
						paymentDTO.setCustId(contractDTO.getCustCardNo());
						paymentDTO.setCustName(contractDTO.getCustName());
					}*/
                    if(StringUtils.isNotEmpty(paymentWithholdDTO.getReqChannel())){
                        paymentDTO.setPaymentChannel(paymentWithholdDTO.getReqChannel());
                    }
                    paymentDTO.setRemark("代扣");
                    paymentDTO.setReqNo(reqNo);
                    PaymentResponse paymentResponse = null;
                    MarvelsLogUtil.getInstance().info(">>>>>>>>手动代扣发起代扣交易请求参数:" + JSONObject.fromObject(paymentDTO));
                    try {
                        paymentResponse = withholdPayment(paymentDTO);
                    } catch (Exception e) {
                        MarvelsLogUtil.getInstance().error(">>>>>>>>手动代扣发起代扣交易异常:", e);
                    }
                    MarvelsLogUtil.getInstance()
                            .info(">>>>>>>>手动代扣发起代扣交易返回参数:" + JSONObject.fromObject(paymentResponse));
                    String status = "";// ；1交易中; 2代扣成功 9代扣失败
                    String rtnOrderNo = "";// 第三方返回订单号
                    String rtnResponseCode = "";// 扣款返回码
                    String rtnResponseMsg = "";// 扣款返回信息
                    BigDecimal amountAct = new BigDecimal("0");// 实际成功金额
                    String resChannel = null;
                    if (null == paymentResponse) {
                        status = "1";
                        rtnResponseMsg = "返回信息为空";
                    } else {
                        resChannel = paymentResponse.getChannel();
                        rtnResponseMsg = paymentResponse.getMsg();
                        rtnOrderNo = paymentResponse.getOrderNumber();
                        rtnResponseCode = paymentResponse.getCode();
                        if ("0".equals(paymentResponse.getCode())) {// 成功
                            status = "2";
                            amountAct = splitAmount[i];
                            succcessAmount = succcessAmount.add(amountAct);
                        }else if(MarvelsConstant.FAILED.equals(paymentResponse.getCode())){//失败
                            status = "9";
                        }else {// 其余做处理中处理
                            status = "1";
                        }
                        PaymentResponse.SingleResult singleResult=new PaymentResponse().new SingleResult();
                        singleResult.setErrorCode(paymentResponse.getCode());
                        singleResult.setErrorMsg(paymentResponse.getMsg());
                        singleResults.add(singleResult);
                    }
                    // 更新代扣流水
                    McfePaymentWithholdDetailDTO detailDTOUpdate = new McfePaymentWithholdDetailDTO();
                    detailDTOUpdate.setId(detailDTO.getId());
                    detailDTOUpdate.setUpdatedBy(userCode);
                    detailDTOUpdate.setUpdatedDate(new Date());
                    detailDTOUpdate.setAmountAct(amountAct);
                    detailDTOUpdate.setStatus(status);// ；1交易中; 2代扣成功 9代扣失败
                    detailDTOUpdate.setRtnOrderNo(rtnOrderNo);
                    // 001 快付通（云科贷） ,002 宝付（云科贷） 003 宝付（口袋） 004 宝付（渤海） 005 支付宝  006 运营

                    detailDTOUpdate.setResChannel(resChannel);
                    detailDTOUpdate.setRtnResponseDate(new Date());
                    detailDTOUpdate.setRtnResponseCode(rtnResponseCode);// 扣款返回码
                    detailDTOUpdate.setRtnResponseMsg(rtnResponseMsg);// 扣款返回信息
                    detailDTOUpdate.setBatchStatus("2");//置为处理完成
                    withholdDetailDao.updateByPrimaryKeySelective(detailDTOUpdate);
                    if ("2".equals(status)) {// 成功
                        detailDTOUpdate.setTransctionSeq(reqNo);
                        withholdSuccess(contractDTO,paymentWithholdDTO,detailDTOUpdate);
                    }
                }
                // 更新代扣总记录
                McfePaymentWithholdDTO withholdDTOUpdate = new McfePaymentWithholdDTO();
                withholdDTOUpdate.setId(paymentWithholdDTO.getId());
                if (paymentWithholdDTO.getAmount().compareTo(succcessAmount) == 0) {
                    withholdDTOUpdate.setStatus("0");// 代扣成功
                    totalResponse.setSuccessAmount(succcessAmount);
                    totalResponse.setCode("0");
                    totalResponse.setMsg("成功");
                } else {
                    withholdDTOUpdate.setStatus("2");//处理中
                    totalResponse.setCode("1");
                    totalResponse.setMsg("处理中");
                }
                withholdDTOUpdate.setAmountAct(succcessAmount);
                withholdDTOUpdate.setUpdatedBy(userCode);
                withholdDTOUpdate.setUpdatedDate(new Date());
                McfePaymentTransferDTO transferDTOUpdate = new McfePaymentTransferDTO();
                BeanUtil.copyProperties(withholdDTOUpdate,transferDTOUpdate);
                transferDao.updateByPrimaryKeySelective(transferDTOUpdate);
                totalResponse.setList(singleResults);
                return totalResponse;
            }
        } catch (Exception e) {
            MarvelsLogUtil.getInstance().error(">>>>>loanId:" + loanId + ",代扣通用方法代扣异常:", e);
            throw new MarvelsBusinessException(e.getMessage());
        } finally {
            if (!CacheUtils.isNotLock(key, loanId)) {// 如果是锁住的将所释放
                CacheUtils.del(key);
            }
        }
        return null;
    }



    /**
     * 展期费代扣成功处理
     * @param withholdDTO
     * @return
     */
    public void extensionwithholdeSuccess(McfePaymentWithholdDTO withholdDTO) throws MarvelsBusinessException{
        extensionwithholdeSuccess(withholdDTO.getLoanId(),withholdDTO.getAmount(),withholdDTO.getExtensionDay());
    }

    /**
     * 展期费冲账
     * @param loanId
     * @param amount
     * @param extensionDay
     * @throws MarvelsBusinessException
     */
    public void extensionwithholdeSuccess(String loanId, BigDecimal amount,int extensionDay) throws MarvelsBusinessException{
        // 查询合同状态
        McfeCustomerLoanContractDTO contractDTO = mcfeCustomerLoanContractDao.selectContractByLoanId(loanId);
        if(contractDTO==null){
            throw new MarvelsBusinessException("合同信息不存在");
        }
        Calendar calendar=Calendar.getInstance();
        //查询还款计划
        List<McfeCustomerRepaymentPlanDTO> planList=mcfeCustomerRepaymentPlanDao.selectAllPlan(loanId);
        if(planList==null || planList.size()<1){
            throw new MarvelsBusinessException("还款计划不存在");
        }
        McfeCustomerRepaymentPlanDTO planDTO=planList.get(0);//只有一条还款计划
        if(contractDTO.getStatus()==1 && !StringUtils.equalsIgnoreCase("Y", CommonProperties.getNewRepaymentFlag())){//逾期状态  取当前时间
            calendar.setTime(new Date());
        }else{//未逾期状态取最迟还款日
            calendar.setTime(planDTO.getPaymentDateLate());
        }
        int actDay=0;
        if(extensionDay!=1){//展期天数为1天则不包含今天  展期天数不为1需要包含今天
            actDay=extensionDay-1;
        }else{
            actDay=extensionDay;
        }
        calendar.add(Calendar.DAY_OF_YEAR, actDay);
        Date paymentDateLate=calendar.getTime();
        //更新合同计划的最迟还款日
        McfeCustomerRepaymentPlanDTO updatePlan=new McfeCustomerRepaymentPlanDTO();
        UserDTO user = null;
        try {
            user=CacheUtils.getCacheUser();
        } catch (Exception e) {
            MarvelsLogUtil.getInstance().error(">>>>获取本地用户信息失败");
        }

        //获取应冲销的滞纳金
        BigDecimal reverseLateAmount = getReverseLateByExtension(loanId,amount,extensionDay);

        String userCode=user==null?"system":user.getUserCode();
        updatePlan.setId(planDTO.getId());
        updatePlan.setUpdatedBy(userCode);
        updatePlan.setDelqDays(0);
        updatePlan.setStatus(0);
        //设置还款计划剩余应还滞纳金信息
        //updatePlan.setLateFee(planDTO.getLateFee().subtract(reverseLateAmount));
        //设置还款计划已还滞纳金信息
        updatePlan.setLateFeeAct((planDTO.getLateFeeAct() == null ? BigDecimal.ZERO : planDTO.getLateFeeAct()).add(reverseLateAmount));
        updatePlan.setUpdatedDate(new Date());
        updatePlan.setPaymentDateLate(paymentDateLate);
        mcfeCustomerRepaymentPlanDao.updateRepaymentPlanById(updatePlan);

        //修改合同表状态和逾期天数
        McfeCustomerLoanContractDTO mcfeCustomerLoanContractDTO=new McfeCustomerLoanContractDTO();
        mcfeCustomerLoanContractDTO.setLoanId(loanId);
        mcfeCustomerLoanContractDTO.setDelqDays(0);
        mcfeCustomerLoanContractDTO.setStatus(0);//正常
        //设置合同已还滞纳金信息
        mcfeCustomerLoanContractDTO.setLateFee(contractDTO.getLateFee().add(reverseLateAmount));
        //设置合同剩余应还滞纳金信息
        mcfeCustomerLoanContractDTO.setLateFeeOs(contractDTO.getLateFeeOs().subtract(reverseLateAmount));
        mcfeCustomerLoanContractDTO.setId(contractDTO.getId());
        mcfeCustomerLoanContractDTO.setUpdatedDate(new Date());
        mcfeCustomerLoanContractDTO.setUpdatedBy(userCode);
        mcfeCustomerLoanContractDao.updateContractStatusByLoanId(mcfeCustomerLoanContractDTO);

        //分期模式时将催收记录置为催回状态
        if(StringUtils.equalsIgnoreCase("Y", CommonProperties.getNewRepaymentFlag())){
            overdueCollectTaskDao.urgentByLoanId(loanId);
        }
    }

    //通过展期费代扣金额和展期天数计算应冲销的滞纳金
    private BigDecimal getReverseLateByExtension(String loanId ,BigDecimal amount,int extensionDay){
        BigDecimal reverseLateAmount = BigDecimal.ZERO;

        //通过展期天数计算不包含滞纳金的展期费用
        ExtensionFunctionEnum[] extensionlist=ExtensionFunctionEnum.enums();
        BigDecimal extensionAmount = BigDecimal.ZERO;
        for(ExtensionFunctionEnum extensionFunctionEnum:extensionlist){
            if(extensionDay == extensionFunctionEnum.getDay()){
                McfeLendingProcess mcfeLendingProcess=mcfeLendingProcessDao.selectByloanIdAndStatus(loanId, "");
                extensionAmount=new BigDecimal(extensionFunctionEnum.getValue()).multiply(mcfeLendingProcess.getPrincipalAmtAct());
                break;
            }
        }
        //应冲销滞纳金=已扣款展期费-（审批核定金额*展期天数利率）
        reverseLateAmount = amount.subtract(extensionAmount);
        return reverseLateAmount;
    }


    /**
     * 持久化冲账流水
     */
    public int persistentFlowDetail(McfeCustomerLoanContractDTO contractDto,McfePaymentWithholdDTO paymentWithholdDTO,McfePaymentWithholdDetailDTO detailDTO) throws MarvelsBusinessException{
        // 持久化还款流水/冲销流水
        McfeRepaymentFlowDTO mcfeRepaymentFlowDto = new McfeRepaymentFlowDTO();
        mcfeRepaymentFlowDto.setAmountAct(detailDTO.getAmountAct());
        mcfeRepaymentFlowDto.setCustName(contractDto.getCustName());
        mcfeRepaymentFlowDto.setCustCardNo(contractDto.getCustCardNo());
        mcfeRepaymentFlowDto.setStatus("0");//冲账状态 0未冲账；1冲账中; 2代扣成功; 3 反冲销
        mcfeRepaymentFlowDto.setLoanId(contractDto.getLoanId());
        mcfeRepaymentFlowDto.setBankCardNo(paymentWithholdDTO.getBankCardNo());
        mcfeRepaymentFlowDto.setBankName(paymentWithholdDTO.getBankName());
        mcfeRepaymentFlowDto.setBankHeadLink(contractDto.getPaymentBankHead());
        mcfeRepaymentFlowDto.setFundCode(contractDto.getFundCode());
        mcfeRepaymentFlowDto.setFundName(contractDto.getFundName());
        mcfeRepaymentFlowDto.setProductType(contractDto.getProductType());
        mcfeRepaymentFlowDto.setProductTypeName(contractDto.getProductTypeName());
        mcfeRepaymentFlowDto.setProductCode(contractDto.getProductCode());
        mcfeRepaymentFlowDto.setProductName(contractDto.getProductName());
        mcfeRepaymentFlowDto.setChannelCode(contractDto.getChannelCode());
        mcfeRepaymentFlowDto.setChannelName(contractDto.getChannelName());
        mcfeRepaymentFlowDto.setAmount(detailDTO.getAmount());
        UserDTO user = null;
        try {
            user=CacheUtils.getCacheUser();
        } catch (Exception e) {
            MarvelsLogUtil.getInstance().error(">>>>获取本地用户信息失败");
        }
        String userCode=user==null?"system":user.getUserCode();
        mcfeRepaymentFlowDto.setCreatedBy(userCode);
        mcfeRepaymentFlowDto.setUpdatedBy(userCode);
        mcfeRepaymentFlowDto.setCreatedDate(new Date());
        mcfeRepaymentFlowDto.setUpdatedDate(new Date());
        mcfeRepaymentFlowDto.setMobile(contractDto.getMobile());
        mcfeRepaymentFlowDto.setRepayStyle(paymentWithholdDTO.getRepayStyle()+"");
        if(StringUtils.isNotEmpty(paymentWithholdDTO.getReqChannel())){
            mcfeRepaymentFlowDto.setReqChannel(paymentWithholdDTO.getReqChannel());
        }
        mcfeRepaymentFlowDto.setResChannel(detailDTO.getResChannel());
        mcfeRepaymentFlowDto.setRtnOrderNo(detailDTO.getRtnOrderNo());
        mcfeRepaymentFlowDto.setRtnResponseCode(detailDTO.getRtnResponseCode());
        mcfeRepaymentFlowDto.setRtnResponseDate(new Date());
        mcfeRepaymentFlowDto.setRtnResponseMsg(detailDTO.getRtnResponseMsg());
        mcfeRepaymentFlowDto.setPayType(paymentWithholdDTO.getFlowPayType());
        mcfeRepaymentFlowDto.setTranctionDate(new Date());
        mcfeRepaymentFlowDto.setTransctionSeq(detailDTO.getTransctionSeq());
        return mcfeRepaymentFlowDao.insertSelective(mcfeRepaymentFlowDto);
    }

    /**
     *
     * @Title: withholdPreSettleDeal
     * @Description:提前结清
     * @param paymentWithholdDTO
     * @return
     * @throws MarvelsBusinessException
     * @author 李瑶
     * @date 2018年10月20日 下午2:05:28
     */
    @Override
    public PaymentResponse withholdPreSettleDeal(McfePaymentWithholdDTO paymentWithholdDTO)
            throws MarvelsBusinessException {
        // 提前结清
        String loanId = paymentWithholdDTO.getLoanId();
        if (StringUtils.isEmpty(loanId)) {
            throw new MarvelsBusinessException("loanId不能为空");
        }
        if (paymentWithholdDTO.getAmount() == null || paymentWithholdDTO.getAmount().compareTo(BigDecimal.ZERO) < 1) {
            throw new MarvelsBusinessException("金额必须大于0,loanId:"+loanId);
        }
//		if (StringUtils.isEmpty(paymentWithholdDTO.getBankHeadLink())) {
//			throw new MarvelsBusinessException("支行不能为空");
//		}
        if (StringUtils.isEmpty(paymentWithholdDTO.getBankCardNo())) {
            throw new MarvelsBusinessException("银行卡号不能为空,loanId:"+loanId);
        }
        if (StringUtils.isEmpty(paymentWithholdDTO.getBankName())) {
            throw new MarvelsBusinessException("银行名称不能为空,loanId:"+loanId);
        }
        if (StringUtils.isEmpty(paymentWithholdDTO.getCustCardNo())) {
            throw new MarvelsBusinessException("身份证号不能为空,loanId:"+loanId);
        }
        if (StringUtils.isEmpty(paymentWithholdDTO.getTransctionSeq())) {
            throw new MarvelsBusinessException("请求编号不能为空,loanId:"+loanId);
        }
        if (StringUtils.isEmpty(paymentWithholdDTO.getRepayStyle())) {
            throw new MarvelsBusinessException("还款方式不能为空,loanId:"+loanId);
        }
        if (StringUtils.isEmpty(paymentWithholdDTO.getFlowPayType())) {
            throw new MarvelsBusinessException("还款类型不能为空,loanId:"+loanId);
        }
        // 加锁 避免重复插入数据
        String key = RedisKeyConstant.HAND_PAYMENT_WITHHOLD + loanId;
        boolean isNotLock = false;
        try {
            isNotLock = CacheUtils.isNotLock(key, loanId);
            if (isNotLock) {
                // 先将这个key设置过期时间
                CacheUtils.setExpire(key, 60);
                HandWithholdConditionDTO conditionDTO = new HandWithholdConditionDTO();
                conditionDTO.setLoanId(loanId);
                Page<HandWithholdListDTO> contractDtoList = mcfeCustomerLoanContractDao.selectWithholdApplyList(conditionDTO);
                if (null == contractDtoList || contractDtoList.size() < 1) {
                    throw new MarvelsBusinessException("合同信息不存在");
                }
                HandWithholdListDTO contractDto = contractDtoList.get(0);
                if ("2".equals(contractDto.getStatus()) || "3".equals(contractDto.getStatus())
                        || "10".equals(contractDto.getStatus())) {
                    throw new MarvelsBusinessException("进件不处于还款状态");
                }
                // 判断还款计划对应的进件是否有处在交易中的代扣
                McfePaymentWithholdDetailDTO detailDTO = detailDao.selectTradingByLoanId(loanId);
                if (detailDTO != null) {
                    MarvelsLogUtil.getInstance().info(">>>>>>>>>>loanId:" + loanId + ",有处在交易中的代扣");
                    throw new MarvelsBusinessException("存在处理中的代扣,请稍候再试");
                }
                // 判断还款计划对应的进件是否有处在正在冲账中的流水
                McfeRepaymentFlowDTO flowDTO = flowDao.selectDealingByLoanId(loanId);
                if (flowDTO != null) {
                    MarvelsLogUtil.getInstance().info(">>>>>>>>>>loanId:" + loanId + ",有处在冲账中或未冲账的流水");
                    throw new MarvelsBusinessException("存在未冲账的流水,请稍候再试");
                }
                String userCode = "system";
                // 插入代扣
                paymentWithholdDTO.setPayCount(1);
                paymentWithholdDTO.setStatus("2");// 代扣中
                paymentWithholdDTO.setCreatedBy(userCode);
                paymentWithholdDTO.setCreatedDate(new Date());
                paymentWithholdDTO.setUpdatedBy(userCode);
                paymentWithholdDTO.setUpdatedDate(new Date());
                if(StringUtil.isEmpty(paymentWithholdDTO.getWithholdCode())) {
                    paymentWithholdDTO.setWithholdCode(paymentWithholdDTO.getTransctionSeq());
                    if(StringUtil.isEmpty(paymentWithholdDTO.getWithholdCode())) {
                        paymentWithholdDTO.setWithholdCode(GenerateReqNoUtils.transctionReq("DK"));
                    }
                }
                McfePaymentTransferDTO mcfePaymentTransferDTO = new McfePaymentTransferDTO();
                BeanUtil.copyProperties(paymentWithholdDTO,mcfePaymentTransferDTO);
                int count = transferDao.insertSelective(mcfePaymentTransferDTO);
                if (count < 1) {
                    throw new MarvelsBusinessException("持久化代扣申请失败");
                }
                BigDecimal succcessAmount = new BigDecimal("0.00");
                // 代扣明细
                String reqNo = GenerateReqNoUtils.transctionReq("TX");
                detailDTO = new McfePaymentWithholdDetailDTO();
                detailDTO.setAmount(paymentWithholdDTO.getAmount());
                detailDTO.setBankCardNo(paymentWithholdDTO.getBankCardNo());
                detailDTO.setBankHeadLink(paymentWithholdDTO.getBankHeadLink());
                detailDTO.setBankName(paymentWithholdDTO.getBankName());
                detailDTO.setChannelCode(paymentWithholdDTO.getChannelCode());
                detailDTO.setChannelName(paymentWithholdDTO.getChannelName());
                detailDTO.setCreatedBy(userCode);
                detailDTO.setCreatedDate(new Date());
                detailDTO.setCustCardNo(paymentWithholdDTO.getCustCardNo());
                detailDTO.setCustName(paymentWithholdDTO.getCustName());
                detailDTO.setFundCode(paymentWithholdDTO.getFundCode());
                detailDTO.setFundName(paymentWithholdDTO.getFundName());
                detailDTO.setLoanId(paymentWithholdDTO.getLoanId());
                detailDTO.setMobile(paymentWithholdDTO.getMobile());
                detailDTO.setPayType(String.valueOf(paymentWithholdDTO.getPayType()));
                detailDTO.setProductCode(paymentWithholdDTO.getProductCode());
                detailDTO.setProductName(paymentWithholdDTO.getProductName());
                detailDTO.setProductType(paymentWithholdDTO.getProductType());
                detailDTO.setProductTypeName(paymentWithholdDTO.getProductTypeName());
                if(StringUtils.isNotEmpty(paymentWithholdDTO.getReqChannel())){
                    detailDTO.setReqChannel(paymentWithholdDTO.getReqChannel());
                }
                detailDTO.setStatus("1");// 交易中
                detailDTO.setTranctionDate(new Date());
                detailDTO.setTransctionSeq(reqNo);
                detailDTO.setUpdatedBy(userCode);
                detailDTO.setUpdatedDate(new Date());
                detailDTO.setWithholdCode(paymentWithholdDTO.getWithholdCode());
                detailDTO.setWithholdCategory(paymentWithholdDTO.getWithholdCategory());
                int detailCount = withholdDetailDao.insertSelective(detailDTO);
                if (detailCount < 1) {
                    throw new MarvelsBusinessException("持久化明细代扣申请失败");
                }


                // 发起代扣
                HandleWithholePaymentDTO paymentDTO = new HandleWithholePaymentDTO();
                paymentDTO.setAmount(detailDTO.getAmount());
                paymentDTO.setBankName(detailDTO.getBankName());
                paymentDTO.setCustBankAccountNo(detailDTO.getBankCardNo());
                paymentDTO.setCustBankAcctType("1");
                paymentDTO.setCustBindPhoneNo(detailDTO.getMobile());
                paymentDTO.setCustId(detailDTO.getCustCardNo());
                paymentDTO.setCustName(detailDTO.getCustName());
                paymentDTO.setFundSource(detailDTO.getFundCode());
                paymentDTO.setLoanId(detailDTO.getLoanId());
                paymentDTO.setMerchantTreatyNo(detailDTO.getLoanId());
                if (StringUtils.isNotEmpty(detailDTO.getReqChannel())) {
                    paymentDTO.setPaymentChannel(detailDTO.getReqChannel());
                }
                paymentDTO.setRemark("提前结清代扣");
                paymentDTO.setReqNo(detailDTO.getTransctionSeq());
                PaymentResponse paymentResponse = null;
                MarvelsLogUtil.getInstance().info(">>>>>>>>提前结清代扣发起代扣交易请求参数:" + JSONObject.fromObject(paymentDTO));
                try {
                    paymentResponse = withholdPayment(paymentDTO);
                } catch (Exception e) {
                    MarvelsLogUtil.getInstance().error(">>>>>>>>提前结清代扣发起代扣交易异常:", e);
                }
                MarvelsLogUtil.getInstance().info(">>>>>>>>提前结清代扣发起代扣交易返回参数:" + JSONObject.fromObject(paymentResponse));
                String status = "";// ；1交易中; 2代扣成功 9代扣失败
                String rtnOrderNo = "";// 第三方返回订单号
                String rtnResponseCode = "";// 扣款返回码
                String rtnResponseMsg = "";// 扣款返回信息
                BigDecimal amountAct = new BigDecimal("0");// 实际成功金额
                String resChannel = null;
                if (null == paymentResponse) {
                    status = "1";
                    rtnResponseMsg = "返回信息为空";
                } else {
                    resChannel = paymentResponse.getChannel();
                    rtnResponseMsg = paymentResponse.getMsg();
                    rtnOrderNo = paymentResponse.getOrderNumber();
                    rtnResponseCode = paymentResponse.getCode();
                    if ("0".equals(paymentResponse.getCode())) {// 成功
                        status = "2";
                        amountAct = paymentDTO.getAmount();
                    }else if(MarvelsConstant.FAILED.equals(paymentResponse.getCode())){//失败
                        status = "9";
                    }else {// 其余做处理中处理
                        status = "1";
                    }
                    // 001 快付通（云科贷） ,002 宝付（云科贷） 003 宝付（口袋） 004 宝付（渤海） 005 支付宝
                    // 006 运营

                }
                // 更新代扣流水
                McfePaymentWithholdDetailDTO detailDTOUpdate = new McfePaymentWithholdDetailDTO();
                detailDTOUpdate.setId(detailDTO.getId());
                detailDTOUpdate.setLoanId(detailDTO.getLoanId());
                detailDTOUpdate.setUpdatedBy(userCode);
                detailDTOUpdate.setUpdatedDate(new Date());
                detailDTOUpdate.setAmountAct(amountAct);
                detailDTOUpdate.setStatus(status);// ；1交易中; 2代扣成功 9代扣失败
                detailDTOUpdate.setRtnOrderNo(rtnOrderNo);
                detailDTOUpdate.setResChannel(resChannel);
                detailDTOUpdate.setRtnResponseDate(new Date());
                detailDTOUpdate.setRtnResponseCode(rtnResponseCode);// 扣款返回码
                detailDTOUpdate.setRtnResponseMsg(rtnResponseMsg);// 扣款返回信息
                int updateCount = withholdDetailDao.updateByPrimaryKeySelective(detailDTOUpdate);
                if ("2".equals(status)) {// 成功
                    // 持久化还款流水/冲销流水
                    McfeRepaymentFlowDTO mcfeRepaymentFlowDto = new McfeRepaymentFlowDTO();
                    mcfeRepaymentFlowDto.setAmountAct(detailDTO.getAmountAct());
                    mcfeRepaymentFlowDto.setCustName(detailDTO.getCustName());
                    mcfeRepaymentFlowDto.setCustCardNo(detailDTO.getCustCardNo());
                    mcfeRepaymentFlowDto.setStatus("0");//冲账状态 0未冲账；1冲账中; 2代扣成功; 3 反冲销
                    mcfeRepaymentFlowDto.setLoanId(detailDTO.getLoanId());
                    mcfeRepaymentFlowDto.setBankCardNo(detailDTO.getBankCardNo());
                    mcfeRepaymentFlowDto.setBankName(detailDTO.getBankName());
                    mcfeRepaymentFlowDto.setBankHeadLink(detailDTO.getBankHeadLink());
                    mcfeRepaymentFlowDto.setFundCode(detailDTO.getFundCode());
                    mcfeRepaymentFlowDto.setFundName(detailDTO.getFundName());
                    mcfeRepaymentFlowDto.setProductType(detailDTO.getProductType());
                    mcfeRepaymentFlowDto.setProductTypeName(detailDTO.getProductTypeName());
                    mcfeRepaymentFlowDto.setProductCode(detailDTO.getProductCode());
                    mcfeRepaymentFlowDto.setProductName(detailDTO.getProductName());
                    mcfeRepaymentFlowDto.setChannelCode(detailDTO.getChannelCode());
                    mcfeRepaymentFlowDto.setChannelName(detailDTO.getChannelName());
                    mcfeRepaymentFlowDto.setCreatedBy(userCode);
                    mcfeRepaymentFlowDto.setUpdatedBy(userCode);
                    mcfeRepaymentFlowDto.setCreatedDate(new Date());
                    mcfeRepaymentFlowDto.setUpdatedDate(new Date());
                    mcfeRepaymentFlowDto.setMobile(detailDTO.getMobile());
                    mcfeRepaymentFlowDto.setRepayStyle(detailDTO.getPayType());
                    if (StringUtils.isNotEmpty(detailDTO.getReqChannel())) {
                        mcfeRepaymentFlowDto.setReqChannel(detailDTO.getReqChannel());
                    }
                    mcfeRepaymentFlowDto.setResChannel(resChannel);
                    mcfeRepaymentFlowDto.setRtnOrderNo(rtnOrderNo);
                    mcfeRepaymentFlowDto.setRtnResponseCode(rtnResponseCode);
                    mcfeRepaymentFlowDto.setRtnResponseDate(new Date());
                    mcfeRepaymentFlowDto.setRtnResponseMsg(rtnResponseMsg);
                    if ("10".equals(detailDTO.getPayType()) || "3".equals(detailDTO.getPayType())) {
                        mcfeRepaymentFlowDto.setPayType("1");
                    } else {
                        mcfeRepaymentFlowDto.setPayType("2");
                    }
                    mcfeRepaymentFlowDto.setTranctionDate(new Date());
                    mcfeRepaymentFlowDto.setTransctionSeq(detailDTO.getTransctionSeq());
                    mcfeRepaymentFlowDao.insertSelective(mcfeRepaymentFlowDto);
                }
                // 更新代扣总记录
                McfePaymentWithholdDTO withholdDTOUpdate = new McfePaymentWithholdDTO();
                withholdDTOUpdate.setLoanId(paymentWithholdDTO.getLoanId());
                if ("2".equals(status)) {
                    withholdDTOUpdate.setStatus("1");// 代扣成功
                } else {
                    withholdDTOUpdate.setStatus("2");// 处理中
                }
                withholdDTOUpdate.setAmountAct(paymentDTO.getAmount());
                withholdDTOUpdate.setUpdatedBy(userCode);
                withholdDTOUpdate.setUpdatedDate(new Date());
                McfePaymentTransferDTO transferDTOUpdate = new McfePaymentTransferDTO();
                BeanUtil.copyProperties(withholdDTOUpdate,transferDTOUpdate);
                transferDao.updateByPrimaryKeySelective(transferDTOUpdate);
                return paymentResponse;
            }
            return null;
        } catch (Exception e) {
            MarvelsLogUtil.getInstance().error(">>>>>loanId:" + loanId + ",提前结清-代扣还款-审批通过异常:", e);
            throw new MarvelsBusinessException(e.getMessage());
        } finally {
            if (!CacheUtils.isNotLock(key, loanId)) {// 如果是锁住的将所释放
                CacheUtils.del(key);
            }
        }
    }


    @Override
    public void withholdSuccess(McfeCustomerLoanContractDTO contractDto, McfePaymentWithholdDTO paymentWithholdDTO,
                                McfePaymentWithholdDetailDTO detailDTO) throws MarvelsBusinessException {
        String withholdCategory=paymentWithholdDTO.getWithholdCategory();
        if(withholdCategory.equals("1") || StringUtils.isEmpty(withholdCategory)){//如果是扣还款金额 则持久化冲账流水
            persistentFlowDetail(contractDto,paymentWithholdDTO,detailDTO);
        }else if(withholdCategory.equals("2")){//扣展期费成功逻辑
            extensionwithholdeSuccess(paymentWithholdDTO);
        }
    }

    public static void main(String[] args) {
        BigDecimal aa = BigDecimal.valueOf(300.005);
        System.out.println(aa.toString());
        System.out.println(aa.setScale(2, BigDecimal.ROUND_HALF_UP));
    }

    @Override
    public McfeCustomerLoanContractDTO synchronizedBankCard(McfeCustomerLoanContractDTO contractDto,String channel){
        String custCardNo=contractDto.getCustCardNo();
        String loanId=contractDto.getLoanId();
        if(StringUtils.isEmpty(custCardNo)){
            return contractDto;
        }
        if(StringUtils.isEmpty(loanId)){
            return contractDto;
        }
        try {
            if(StringUtils.isEmpty(channel)){
                channel = ServerProperties.getValue(configPropertiesPath, "common.properties", "payment_channel");
            }
            //查询当前支付通道的绑卡记录的最后一条
            McfePaymentUserBindCard mcamPaymentUserBindCards=new McfePaymentUserBindCard();
            mcamPaymentUserBindCards.setIdno(custCardNo);
            mcamPaymentUserBindCards.setChannel(channel);
            mcamPaymentUserBindCards = mcamPaymentUserBindCardMapper.selectBindCard(mcamPaymentUserBindCards);
            if(mcamPaymentUserBindCards!=null){//绑卡记录不为空 同步银行卡信息
                //银行卡不一致同步还款计划 合同的银行卡信息
                if(!contractDto.getPaymentAcctNo().equals(mcamPaymentUserBindCards.getBankCardNo())){
                    //更新合同信息
                    McfeCustomerLoanContractDTO loanContractDTO=new McfeCustomerLoanContractDTO();
                    loanContractDTO.setPaymentAcctNo(mcamPaymentUserBindCards.getBankCardNo());
                    loanContractDTO.setPaymentBankName(mcamPaymentUserBindCards.getBankName());
                    loanContractDTO.setMobile(mcamPaymentUserBindCards.getPhone());
                    loanContractDTO.setLoanId(loanId);
                    String userCode=null;
                    UserDTO user = null;
                    try {
                        user=CacheUtils.getCacheUser();
                    } catch (Exception e) {
                    }
                    if(user==null){
                        userCode="system";
                    } else{
                        userCode=user.getUserCode();
                    }
                    loanContractDTO.setUpdatedBy(userCode);
                    loanContractDTO.setUpdatedDate(new Date());
                    mcfeCustomerLoanContractDao.updateContractBankInfoByLoanId(loanContractDTO);

                    contractDto.setPaymentAcctNo(mcamPaymentUserBindCards.getBankCardNo());
                    contractDto.setPaymentBankName(mcamPaymentUserBindCards.getBankName());
                    contractDto.setMobile(mcamPaymentUserBindCards.getPhone());
                }
            }

        } catch (Exception e) {
            MarvelsLogUtil.getInstance().error(">>>>>loanId:"+loanId+"同步合同银行卡信息异常:",e);
        }
        return contractDto;
    }
}
